package com.zx.crowdfunding.security;

import java.util.LinkedHashSet;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

import com.zx.crowdfunding.entity.Admin;
import com.zx.crowdfunding.entity.Menu;
import com.zx.crowdfunding.service.api.AdminService;
import com.zx.crowdfunding.service.api.AuthService;
import com.zx.crowdfunding.service.api.MenuService;
import com.zx.crowdfunding.service.api.RoleService;

/**
 * 自定义UserDetailsService接口实现类
 * @author 郑雪
 * @date 2021-12-11
 */
@Component
public class CrowdFundingUserDetailsService implements UserDetailsService {
	
	/**
	 * 日志
	 */
	Logger logger = LoggerFactory.getLogger(CrowdFundingUserDetailsService.class);
	
	/**
	 * 管理员Service接口
	 */
	@Autowired 
	private AdminService adminService;
	
	/**
	 * 角色Service接口
	 */
	@Autowired 
	private RoleService roleService;
	
	/**
	 * 权限Service接口
	 */
	@Autowired 
	private AuthService authService;
	
	/**
	 * 菜单Service接口
	 */
	@Autowired 
	private MenuService menuService;

	/**
	 * 通过用户名加载用户
	 * 根据用户名查询数据库，把查询出来的用户名密码和权限封装为User对象返回
	 */
	@Override
	public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException {
		
		// 根据登录账号查询Admin对象
		Admin admin = adminService.getAdminByLoginAcct(username);
		
		// 获取adminId
		Integer adminId = admin.getId();
		
		// 根据adminId获取GrantedAuthority对象的集合
		List<GrantedAuthority> authorities = authService.getGrantedAuthorityListByAdminId(adminId);
		
		// 根据adminId查询树形结构的菜单集合
		LinkedHashSet<Menu> menuSet = menuService.getMenuByAdminId(adminId);
		
		// 把查询出来的菜单列表存入管理员对象中
		admin.setMenu(menuSet);
		
		logger.debug("menuSet : " + menuSet);
		
		// 返回自定义的User对象
		return new SecurityAdmin(admin, authorities);
	}
	
}
